package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.enums.errorcodes.AssembleErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/07/15 16:04
 */
@Service("assembleAnalyticalServiceImpl")
public class AssembleValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    @Resource
    private SaasProductHelp saasProductHelp;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private AnalyticalHelp analyticalHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.ASSEMBLE.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
        //没有负责团队的 单负责人
        userTeamHelp.checkPermissionOptionTeam(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        JSONObject data = validateDataDTO.getData();
        String corpid = validateDataDTO.getCorpid();
        Long dataId = validateDataDTO.getDataId();
        Long taskId = validateDataDTO.getTaskId();
        boolean isNew = analyticalHelp.isNew(validateDataDTO.getDataId(), validateDataDTO.getTaskId(), corpid);
        // 解析出库仓库，处理前端传参数据
        SaveFormatHelp.formatLinkBusiness4Save(data, AssembleEnum.OUT_WAREHOUSE_ID.getAttr(),AssembleEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), AssembleEnum.OUT_WAREHOUSE_ID.getFieldType());
        // 解析入库仓库，处理前端传参数据
        SaveFormatHelp.formatLinkBusiness4Save(data,AssembleEnum.INTO_WAREHOUSE_ID.getAttr(),AssembleEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), AssembleEnum.INTO_WAREHOUSE_ID.getFieldType());
        validateDataDTO.setData(data);
        // 装配单参数保存前对相关参数进行合理化校验
        parameterCheck(validateDataDTO);
        //序列号必填校验
        SaveFormatHelp.batchSaveRequiredCheck(validateDataDTO);
        // 冗余相关数据信息
//        redundantDataProcessing(validateDataDTO);
        Long date= data.getLong(AssembleEnum.ASSEMBLE_TIME.getAttr());
        //结账中校验
        String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
        if (StringUtil.isNotEmpty(redisHelperValue)) {
            if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))){
                throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
            }
        }
        SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
        //校验日期是否受结账限制
        if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
            if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212051);
            }
        }
        if (isNew) {
            String value = paasRedisHelper.getValue(RedisPrefixConstant.PRODUCE_STOCK_FLOW, corpid);
            if (StringUtil.isNotEmpty(value)) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212038);
            }
            // 新建时校验仓库是否存在
            Long outWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(data, AssembleEnum.OUT_WAREHOUSE_ID.getAttr(), 0L);
            JSONArray outProductArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,AssembleEnum.OUT_PRODUCTS.getAttr(),new JSONArray());
            JSONArray inProductArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,AssembleEnum.IN_PRODUCTS.getAttr(),new JSONArray());
            validateDataOutProduct(outProductArray,inProductArray,corpid,outWarehouseId);
        }
    }

    public void validateDataOutProduct(JSONArray outProductArray,JSONArray inProductArray,String corpid,Long outWarehouseId) throws XbbException {
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Object object:outProductArray) {
            JSONObject jsonObject = (JSONObject) object;
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
            Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            Double num = productNumMap.getOrDefault(productId,0D);
            num += productNum;
            productNumMap.put(productId,num);
        }
        for (Object object:inProductArray) {
            JSONObject jsonObject = (JSONObject) object;
            Long productId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
            Double productNum = jsonObject.getDouble(SelectProductEnum.NUM.getAttr());
            Double num = productNumMap.getOrDefault(productId,0D);
            num += productNum;
            productNumMap.put(productId,num);
        }
        saasProductHelp.productExit(corpid,new ArrayList<>(pageProductIds));
        boolean outStockRule = true;
        FormConfigEntity formConfigEntity = formConfigModel.getEntityByBusinessType(corpid, XbbRefTypeEnum.OUTSTOCK.getCode(), FormConfigEnum.OUTSTOCK_INSUFFICIENT_NOT_ALLOW_WAREHOUSING.getConfig());
        if (Objects.nonNull(formConfigEntity)) {
            if (!Objects.equals(formConfigEntity.getConfigValue(), "1")) {
                outStockRule = false;
            }
        }
        if (outStockRule){
            saasProductHelp.warehouseProductNumLegalCheck(corpid,outProductArray,outWarehouseId,false, OutstockTypeEnum.ASSEMBLE_OUTSTOCK.getCode());
        } else {
            // 解析装配出库产品的仓库字段
            for (int i = 0; i < outProductArray.size(); i++) {
                JSONObject productObj = outProductArray.getJSONObject(i);
                SaveFormatHelp.formatLinkBusiness4Save(productObj,SelectProductEnum.WAREHOUSE.getAttr(),"warehouseName", FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            }
        }
        // 解析装配入库产品的仓库字段
        for (int i = 0; i < inProductArray.size(); i++) {
            JSONObject productObj = inProductArray.getJSONObject(i);
            SaveFormatHelp.formatLinkBusiness4Save(productObj,SelectProductEnum.WAREHOUSE.getAttr(),"warehouseName",FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
        }
    }
    /**
     * 产品参数保存前对相关参数进行合理化校验
     *
     * @param validateDataDTO 前端传参数据
     * @throws XbbException 参数不符合要求错误提醒
     * @author Jian.Wang
     * @date 2019/2/22 14:03
     * @since v1.0
     */
    private void parameterCheck(ValidateDataDTO validateDataDTO) throws XbbException {
        JSONObject data = validateDataDTO.getData();
        String assembleSheetNo = validateDataDTO.getSerialNo();
        // 调拨单编号长度校验
        int assembleSheetNoMax = 100;
        if (assembleSheetNo != null && assembleSheetNo.length() > assembleSheetNoMax) {
            throw new XbbException(AssembleErrorCodeEnum.API_ERROR_231014);
        }
        // 入库仓库必填校验
        Long intoWarehouseId = data.getLong(AssembleEnum.INTO_WAREHOUSE_ID.getAttr());
        if (null == intoWarehouseId) {
            throw new XbbException(AssembleErrorCodeEnum.API_ERROR_231007);
        }
        // 出库仓库必填校验
        Long outWarehouseId = data.getLong(AssembleEnum.OUT_WAREHOUSE_ID.getAttr());
        if (null == outWarehouseId) {
            throw new XbbException(AssembleErrorCodeEnum.API_ERROR_231008);
        }
        // 导入可能会有填批次的情况
        Long dataId = validateDataDTO.getDataId();
    }
}
